package thread.wang_bao_ling.c22.executors;

import org.junit.Test;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
 * Timer使用示例
 * 其内部使用一个线程不断的从任务队列（基于小丁堆实现，离执行时间越近的在顶部）中获取任务，如果最顶部的任务都还没到执行时间则进行阻塞一段时间（及阻塞当前时间距离任务执行的时间差）
 * 缺点：
 * 只有一个线程处理任务，如果抛出异常则任务调度直接结束了
 * 只有一个任务线程处理任务，如果某个任务执行时间较长，会影响下个任务执行
 *
 * 固定时延打印和固定速率区别
 * 主要是计算下一次执行的逻辑不一样，固定延时是相对当前时间再加延时，而固定速率是先对当前重复任务的执行开始时间加延时
 */
public class TimerTest {

    /**
     * 演示任务间相互影响
     * @throws InterruptedException
     */
    @Test
    public void testInfluence() throws InterruptedException {
        Timer timer = new Timer();
        //task1 执行要两秒
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task1 begin---->"+Thread.currentThread().getName()+"---->currentTime:" + System.currentTimeMillis() / 1000);
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("task2---->"+Thread.currentThread().getName()+"---->currentTime:" + System.currentTimeMillis() / 1000);
            }
        };
        //这个task1执行要2s
        timer.schedule(task1, 0);
        timer.scheduleAtFixedRate(task2, 0,1000);

        TimeUnit.SECONDS.sleep(20); //防止单元测试线程直接结束
    }

    /**
     * 测试固定延时打印
     * 这个延时计算方式和ScheduledExecutorService是不同的,Timer中计算固定延时任务的下次执行时间是在当前任务执行前，这个和ScheduledExecutorService相反
     * 计算逻辑和ScheduledExecutorService固定延时一致，都为now()+延时
     * @throws InterruptedException
     */
    @Test
    public void testScheduleWithFixedDelay() throws InterruptedException {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"----currentTime:" + System.currentTimeMillis() / 1000);
            }
        }, 0, 1000);

        TimeUnit.SECONDS.sleep(20); //防止单元测试线程直接结束
    }

    /**
     * 测试固定速率延时打印
     * 这个延时计算方式和ScheduledExecutorService是不同的,Timer中计算固定速率任务的下次执行时间是在当前任务执行前，这个和ScheduledExecutorService相反
     * 计算逻辑和ScheduledExecutorService固定速率一致，都为当前任务执行时间+延时
     * @throws InterruptedException
     */
    @Test
    public void testScheduleAtFixedRate() throws InterruptedException {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"----currentTime:" + System.currentTimeMillis() / 1000);
            }
        }, 0, 1000);

        TimeUnit.SECONDS.sleep(20); //防止单元测试线程直接结束
    }


}
